﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Project2.容器
{
    public class MyList<T>
    {
        //字段
        private const int _defaultCapacity = 4;

        private T[] _items;//内置数组

        private int _size;//数量

        private int _version;//版本

        private static readonly T[] _emptyArray = new T[0];

        /// <summary>
        /// 属性
        /// </summary>
        public int Capacity
        {
            get
            {
                return _items.Length;
            }

            //设置容量
            set
            {
                if (value < _size)
                {
                    throw new ArgumentOutOfRangeException("容量太小");
                }

                if (value == _items.Length)
                {
                    return;
                }

                if (value > 0)
                {
                    T[] array = new T[value];//新建一个空白数组
                    if (_size > 0)
                    {
                        Array.Copy(_items, 0, array, 0, _size);//把老数据复制过来
                    }

                    _items = array;
                }
                else
                {
                    _items = _emptyArray;//容量设置为0
                }
            }
        }

        public int Count
        {
            get { return _size; }
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="items"></param>
        public MyList(T[] items)
        { //使用数组初始化列表
            _items = items;
        }

        public MyList()
        {
            _items = _emptyArray;//初始化列表
        }

        public MyList(int capacity)
        {
            if (capacity < 0)
            {
                throw new ArgumentOutOfRangeException("List长度不能小于0");
            }
            // Capacity = capacity;//必要性？需要读取的时候重新算

            if (capacity == 0)
            {
                _items = _emptyArray;
            }
            else
            {
                _items = new T[capacity];
            }
        }

        /// <summary>
        /// 索引器[]
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentOutOfRangeException"></exception>

        public T this[int index]
        {
            get
            {
                if (index >= _size)
                {
                    throw new ArgumentOutOfRangeException("index不能大于等于数组的长度");
                }
                return _items[index];//只有列表有索引器的原因是，这个数组可以随机访问
            }

            //这个索引只能修改，不能新增数据
            set
            {
                if (index >= _size)
                {
                    throw new ArgumentOutOfRangeException("index不能大于等于数组的长度");
                }
                _items[index] = value;
                _version++;
            }
        }

        //增删改查
        //加到列表最后

        public void Add(T item)
        {
            if (_size == _items.Length)
            {
                //扩容

                EnsureCapacity(_size + 1);
            }

            _items[_size++] = item;
            _version++;
        }

        public void Insert(int index, T item)
        {
            if (index >= _size)
            {
                throw new ArgumentOutOfRangeException("index不能大于等于数组的长度");
            }
            if (_size == _items.Length)//数组满的时候没法插入，先扩充
            {
                EnsureCapacity(_size + 1);
            }
            if (index < _size)//在数组之间插，先移动
            {
                Array.Copy(_items, index, _items, index + 1, _size - index);
            }
            _items[index] = item;
            _size++;
            _version++;
        }

        public int IndexOf(T item)
        {
            return Array.IndexOf(_items, item, 0, _size);
            //找不到的会返回-1
        }

        public void RemoveAt(int index)
        {
            if (index >= _size)
            {
                throw new ArgumentOutOfRangeException("index不能大于等于数组的长度");
            }
            _size--;
            //除去要删除的，后面的往前移
            Array.Copy(_items, index + 1, _items, index, _size - index);
            //最后一个元素置为0
            _items[_size] = (T)default;
            _version++;
        }

        public bool Remove(T item)
        {
            int removeIndex = IndexOf(item);
            if (removeIndex >= 0)
            {
                RemoveAt(removeIndex);
                return true;
            }
            return false;
        }

        public void Clear()
        {
            if (_size > 0)
            {
                Array.Clear(_items, 0, _size);
                _size = 0;
            }
            _version++;
        }

        public bool Contains(T item)
        {
            //空元素也要判断
            if (item == null)
            {
                for (int i = 0; i < _size; i++)
                {
                    if (_items[i] == null)
                    {
                        return true;
                    }
                }
                return false;
            }
            for (int j = 0; j < _size; j++)
            {
                if (item.Equals(_items[j]))
                {
                    return true;
                }
            }
            return false;
        }

        private void EnsureCapacity(int v)
        {
            if (_items.Length < v)
            {
                //扩容
                int newLength = (_items.Length == 0) ? 4 : _items.Length * 2;

                Capacity = newLength;//属性会触发访问器的扩容
            }
        }
    }
}